package nancal.mp.mvc.ops

import io.kubernetes.client.openapi.ApiClient
import nancal.mp.db.mongo.JenkinsLanguageEnum
import nancal.mp.db.mongo.entity.sys.K8sSyncSetting
import nancal.mp.db.mongo.mor
import nancal.mp.db.redis.rer
import nancal.mp.feign.RegistryClient
import nancal.mp.imageNameVersion
import nancal.mp.model.K8sAppServiceInfo
import nancal.mp.model.K8sAppServiceStatusInfo
import nancal.mp.service.K8sBaseService
import nancal.mp.service.K8sDeploymentService
import nancal.mp.service.SshSyncService
import nbcp.base.annotation.DefaultNumberValue
import nbcp.base.comm.ApiResult
import nbcp.base.comm.JsonResult
import nbcp.base.comm.ListResult
import nbcp.base.comm.config
import nbcp.base.extend.AsString
import nbcp.base.extend.HasValue
import nbcp.base.extend.Slice
import nbcp.base.model.SshClient
import nbcp.base.utils.SpringUtil
import nbcp.myoql.db.mongo.query
import org.slf4j.LoggerFactory
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.scheduling.annotation.Async
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock


@RequestMapping("/ops/k8s-ssh")
@RestController
class K8sSshSyncController(val registryClient: RegistryClient) {
    companion object {
        private var lock = ReentrantLock();
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }


    @Autowired
    lateinit var k8sDeployment: K8sDeploymentService;

    data class K8sVersionStatus(
        var version: String = "",
        var replicas: Int = 0,
        var readyReplicas: Int = 0,
    )

    data class SyncK8sServiceModel(
        var uat: K8sVersionStatus = K8sVersionStatus(),
        var prod: K8sVersionStatus = K8sVersionStatus(),
//        var registryReady: Boolean = false
    ) : K8sAppServiceStatusInfo()


    @RequestMapping("/list-test-prod", method = arrayOf(RequestMethod.POST, RequestMethod.GET))
    fun listTestProd(
        namespace: String,
        name: String,
        language: JenkinsLanguageEnum?,
        isReady: Boolean?,
        skip: Int,
        @DefaultNumberValue(99) take: Int
    ): ListResult<SyncK8sServiceModel> {
        return listK8sTestService(namespace, name, language, isReady, skip, take)
    }

//    @RequestMapping("/list-test-uat", method = arrayOf(RequestMethod.POST, RequestMethod.GET))
//    fun listTestUat(
//        namespace: String,
//        name: String,
//        language: JenkinsLanguageEnum?,
//        isReady: Boolean?,
//        skip: Int,
//        @DefaultNumberValue(99) take: Int
//    ): ListResult<SyncK8sServiceModel> {
//
//        return listK8sTestService(namespace, name, language, isReady, skip, take, false)
//    }

    private fun listK8sTestService(
        namespace: String,
        name: String,
        language: JenkinsLanguageEnum?,
        isReady: Boolean?,
        skip: Int,
        take: Int
    ): ListResult<SyncK8sServiceModel> {
        var syncSetting = mor.sys.k8sSyncSetting.query()
            .where { it.isActive mongoEquals true }
            .toEntity()!!;

        var testK8s = K8sBaseService.getK8sClient("");

        var testPods = k8sDeployment.list(
            testK8s,
            namespace,
            name,
            "",
            isReady,
            language,
            "",
            "",
            skip,
            take
        );

        var names = testPods.data.map { it.name }

        var prodK8s = ApiClient();
        prodK8s.setApiKeyPrefix("Bearer")
        prodK8s.isVerifyingSsl = false;


        prodK8s.basePath = syncSetting.prodK8s.apiServerHost
        prodK8s.setApiKey(syncSetting.prodK8s.apiToken);
//            if (isProd) {} else {
//            prodK8s.basePath = syncSetting.uatServer.apiServerHost
//            prodK8s.setApiKey(syncSetting.uatServer.apiToken);
//        }


        var prodPods = names.map {
            var r = k8sDeployment.getDeploymentInfo(
                prodK8s,
                namespace,
                it
            )
            if (r.hasError) {
                return@map null;
            }

            return@map r.data!!
        }.filter { it != null }

        var model = testPods.data.map { row ->
            var syncModel = SyncK8sServiceModel()
            BeanUtils.copyProperties(row, syncModel)

            var prod = prodPods.firstOrNull { it!!.name == row.name };

            if (prod != null) {
                syncModel.prod.version = prod.imageVersion.AsString()
                syncModel.prod.replicas = prod.replicas
                syncModel.prod.readyReplicas = prod.readyReplicas
            }

//            if( syncSetting.prodRegistry.host.HasValue) {
//                syncModel.registryReady = registryClient.getTags(syncSetting.)
//            }

//            if (isProd) {} else {
//                if (prod != null) {
//                    syncModel.uat.version = prod.imageVersion.AsString()
//                    syncModel.uat.replicas = prod.replicas
//                    syncModel.uat.readyReplicas = prod.readyReplicas
//                }
//            }

            return@map syncModel;
        }

        return ListResult.of(model, testPods.total)
    }

    @PostMapping("/fetch-prod-version")
    fun fetchProdVersion(
        namespace: String,
        name: String
    ): ApiResult<K8sAppServiceInfo> {
        var syncSetting = mor.sys.k8sSyncSetting.query()
            .where { it.isActive mongoEquals true }
            .toEntity()!!;

        var prodK8s = ApiClient();
        prodK8s.basePath = syncSetting.prodK8s.apiServerHost.trimEnd('/')
        prodK8s.setApiKey(syncSetting.prodK8s.apiToken);
        prodK8s.setApiKeyPrefix("Bearer")
        prodK8s.isVerifyingSsl = false;


        return k8sDeployment.getDeploymentInfo(
            prodK8s,
            namespace,
            name
        );
    }

//    @PostMapping("/fetch-uat-version")
//    fun fetchUatVersion(
//        namespace: String,
//        name: String
//    ): ApiResult<K8sAppServiceInfo> {
//        var syncSetting = mor.sys.k8sSyncSetting.query()
//            .where { it.isActive mongoEquals true }
//            .toEntity()!!;
//
//        var prodK8s = ApiClient();
//        prodK8s.basePath = syncSetting.uatServer.apiServerHost
//        prodK8s.setApiKey(syncSetting.uatServer.apiToken);
//        prodK8s.setApiKeyPrefix("Bearer")
//        prodK8s.isVerifyingSsl = false;
//
//
//        return k8sDeployment.getDeploymentInfo(
//            prodK8s,
//            namespace,
//            name
//        );
//    }

    @GetMapping("/get-queue")
    fun getQueue(): ApiResult<List<String>> {
        var list = rer.sys.sshSync.getListString();
        SshSyncService.work()
        return ApiResult.of(list);
    }


    @PostMapping("/sync-clear")
    fun clear(): JsonResult {
        var list = rer.sys.sshSync.deleteKey()
        return JsonResult();
    }


    @GetMapping("/get-sync-log")
    fun getSyncLog(name: String): ApiResult<String> {
        var syncSetting = mor.sys.k8sSyncSetting.query()
            .where { it.isActive mongoEquals true }
            .toEntity()!!;

        var ssh = SshClient();
        ssh.host = syncSetting.testSsh.host;
        ssh.port = syncSetting.testSsh.sshPort;
        ssh.userName = syncSetting.testSsh.userName;
        ssh.password = syncSetting.testSsh.password;
        if (ssh.userName.isNullOrEmpty()) {
            return ApiResult.error("ssh 用户名不能为空");
        }

        var result =
            ssh.exec("(cat /data/sync2prod/${name}/sync-task.log 2>/dev/null || true; cat /data/sync2prod/${name}/dep-task.log 2>/dev/null || true)")


        var list = rer.sys.sshSync.getListString();
        result.value = list;
        return result;
    }

    @RequestMapping("/only-sync", method = arrayOf(RequestMethod.POST, RequestMethod.GET))
    fun onlySync(
        namespace: String,
        name: String
    ): JsonResult {
        rer.sys.sshSync.add("sync:${namespace.AsString("default")}:${name}")

        SshSyncService.work();
        return JsonResult();

    }

    /**
     * 同步镜像到生产 reg2.
     */
    @RequestMapping("/sync-to-prod", method = arrayOf(RequestMethod.POST, RequestMethod.GET))
    fun syncToProd(
        namespace: String,
        name: String
    ): JsonResult {
        rer.sys.sshSync.add("deploy:${namespace.AsString("default")}:${name}")

        SshSyncService.work();

        return JsonResult();
    }

//    @RequestMapping("/sync-to-uat", method = arrayOf(RequestMethod.POST, RequestMethod.GET))
//    fun syncToUat(
//        namespace: String,
//        name: String,
//        image: String
//    ): JsonResult {
//        var result = false;
//        try {
//            result = lock.tryLock(1, TimeUnit.SECONDS)
//
//            if (!result) {
//                return JsonResult.error("当前任务正在执行，请稍后再试！");
//            }
//
//            var syncSetting = mor.sys.k8sSyncSetting.query()
//                .where { it.isActive mongoEquals true }
//                .toEntity()!!;
//            return doSyncYml(syncSetting, namespace, name, false, image)
//        } finally {
//            if (result) {
//                lock.unlock();
//            }
//        }
//    }


}